package com.zbc.aspectj;

import com.zbc.annotation.AutoFill;
import com.zbc.constant.AutoFillConstant;
import com.zbc.context.BaseContext;
import com.zbc.enumeration.OperationType;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

@Aspect
@Component
public class AutoFillAspect {
    @Pointcut("@annotation(com.zbc.annotation.AutoFill) && execution(* com.zbc.mapper.*.*(..))")
    public void pointCut(){}

    @Before("pointCut()")
    public void beforeAutoFillAspect(JoinPoint joinPoint) throws InvocationTargetException, IllegalAccessException {
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        Method method = methodSignature.getMethod();
        Object[] args = joinPoint.getArgs();

        AutoFill autoFill = method.getAnnotation(AutoFill.class);

        OperationType value = autoFill.value();

        HashMap<Object,Method[]> methodHashMap = new HashMap<>();

        for(Object arg : args) {
            Class<?> argClass = arg.getClass();
            Method[] methods = argClass.getDeclaredMethods();
            methodHashMap.put(arg,methods);
        }

        if(value.equals(OperationType.INSERT)){
            for(Map.Entry<Object,Method[]> entry : methodHashMap.entrySet()){
                Object key = entry.getKey();
                for(Method m : entry.getValue()){
                    if(m.getName().equals(AutoFillConstant.SET_CREATE_TIME)){
                        m.invoke(key, LocalDateTime.now());
                    }
                    if(m.getName().equals(AutoFillConstant.SET_CREATE_USER)){
                        m.invoke(key, BaseContext.getCurrentId());
                    }
                    if(m.getName().equals(AutoFillConstant.SET_UPDATE_TIME)){
                        m.invoke(key, LocalDateTime.now());
                    }
                    if(m.getName().equals(AutoFillConstant.SET_UPDATE_USER)){
                        m.invoke(key, BaseContext.getCurrentId());
                    }
                }
            }
        } else if(value.equals(OperationType.UPDATE)){
            for(Map.Entry<Object,Method[]> entry : methodHashMap.entrySet()){
                Object key = entry.getKey();
                for(Method m : entry.getValue()){
                    if(m.getName().equals(AutoFillConstant.SET_UPDATE_TIME)){
                        m.invoke(key, LocalDateTime.now());
                    }
                    if(m.getName().equals(AutoFillConstant.SET_UPDATE_USER)){
                        m.invoke(key, BaseContext.getCurrentId());
                    }
                }
            }
        }
    }
}
